//
// Maths.cpp for  in /home/goldbe_y//tek3/Projets/Maths/302graphe
// 
// Made by yoni goldberg
// Login   <goldbe_y@epitech.net>
// 
// Started on  Mon Sep 24 14:39:22 2012 yoni goldberg
// Last update Fri Nov 23 20:39:19 2012 yoni goldberg
//

#include "Matrix.hpp"

// init

Maths::Maths(const std::string &str)
{
  Parse	tmp(str);
  std::cout << "_____MATHS____" << std::endl;
  _dim = tmp.get_dim();
  _coord = tmp.get_vecteurs();
  _h = new float[_dim - 1];
  _y = new float[_dim];
  for (int i = 0; i < _dim - 1; i++)
    _h[i] = _coord[i + 1][0] - _coord[i][0];
  for (int i = 0; i < _dim; i++)
    _y[i] = _coord[i][1]; 

  _vecteur = new float[_dim];
  fill_matrix();
  _rep = new float[_dim];
  for (int i = 0; i < _dim; i++)
    _rep[i] = _vecteur[i];
  pivot();
  _rep[0] = 0;
  _rep[_dim - 1] = 0;
  calc_a();
  calc_b();
  aff_vecteur(_a);
  aff_vecteur(_b);
}

Maths::~Maths()
{
}

void			Maths::fill_matrix()
{
  _matrix = new float*[_dim];
  for (int i = 0; i < _dim; i++)
    _matrix[i] = new float[_dim];
  for (int i = 0; i < _dim; i++)
    for (int j = 0; j < _dim; j++)
      _matrix[i][j] = 0;
  for (int i = 1; i < _dim - 1; i++)
    {
      _matrix[i][i] = 2 * (_h[i] + _h[i - 1]);
      _matrix[i][i + 1] = _h[i - 1];
      _matrix[i][i - 1] = _h[i];
      _vecteur[i - 1] = 6 * (
			     ((_y[i + 1] - _y[i]) / _h[i]) -
			     ((_y[i] - _y[i - 1]) / _h[i - 1])
			     );
    }
}

void			Maths::calc_a()
{
  _a = new float[_dim];
  for (int i = 1; i < _dim - 1; i++)
    _a[i] = (
	     ((_y[i + 1] - _y[i]) / _h[i]) -
	     ((_h[i] / 6) * (_rep[i + 1] - _rep[i]))
	     );
}

void			Maths::calc_b()
{
  _b = new float[_dim];
  for (int i = 1; i < _dim - 1; i++)
    _b[i] = _y[i] - ((_rep[i] * _h[i]) / 6
		     );
}

bool			Maths::is_direct()
{
  for (int i = 1; i < _dim; i++)
    for (int j = 0; j < i; j++)
      if (_matrix[i][j] != 0)
	return false;
  return true;
}

  // operation matrice

void			Maths::sub(int a, int b, float mult)
{
  _rep[a] -= _rep[b] * mult;
  for (int i = 0; i < _dim; i++)
    _matrix[a][i] -= _matrix[b][i] * mult;
}

void			Maths::div(int i, float j)
{
  for (int column = 0; column < _dim; column++)
    _matrix[i][column] /= j;
  _rep[i] /= j;
}

  // algo de gauss

void			Maths::monte()
{
  _rep[_dim - 1] = _vecteur[_dim - 1] / _matrix[_dim - 1][_dim - 1];

  for (int i = 1; i < _dim - 1; i++)
    for (int j = i; j < _dim; j++)
      div(i, _matrix[i][i]);
  for (int i = 1; i < _dim - 1; i++)
    for (int j = i - 1; j >= 0; j--)
      sub(j , i, _matrix[j][i]);
}

void			Maths::descente()
{
  for (int i = 1; i < _dim - 1; i++)
    for (int j = i + 1; j < _dim; j++)
      sub(j, i, _matrix[j][i] / _matrix[i][i]);
}

void			Maths::pivot()
{
  descente();
  monte();
}


  // DEBUG


void			Maths::aff_matrix()
{
  for (int i = 0; i < _dim; i++)
    {
      for (int j = 0; j < _dim; j++)
	std::cout << _matrix[i][j] << " ";
      std::cout << std::endl;
    }
}

float			Maths::calc(int line)
{
  float		temp = 0;

  for (int i = 0; i < _dim; i++)
    temp += (_save_m[line][i] * _vecteur[i]);
  return temp;
}

void			Maths::mult_matrix()
{
  float		*temp = new float[_dim];

  for (int line = 0; line < _dim; line++)
    temp[line] = calc(line);


  for (int i = 0; i < _dim; i++)
    std::cout << _vecteur[i] << std::endl;
  std::cout << std::endl;
  for (int i = 0; i < _dim; i++)
    std::cout << temp[i] - _save_v[i] << std::endl;
}

void			Maths::aff_vecteur(float *vecteur)
{
  for (int i = 0; i < _dim; i++)
    std::cout << vecteur[i] << std::endl;
  std::cout << std::endl;
}
